package com.example.concurrency.juc.lock.semaphore;

import java.util.concurrent.Semaphore;

/**
 * 给定整数N，开启N个线程，依次输出整数 1、2、3 ... N
 */
public class SemaphoreTest {

    public static void main(String[] args) throws InterruptedException {
        //1. 保护重要部分
        example_test_1();
    }

    private static void example_test_1() throws InterruptedException {
        Semaphore semaphore = new Semaphore(1);
        Counter counter = new Counter(semaphore);
        int total = 10;
        for (int i = 1; i <= total; i++) {
            new Thread(new Handler("name" + i, i, counter, total)).start();
        }
        Thread.currentThread().join();
    }

    private static class Counter {
        private volatile int count;
        private Semaphore semaphore;

        public Counter(Semaphore semaphore) {
            this.semaphore = semaphore;
        }

        public int getCount() throws InterruptedException {
            semaphore.acquire();
            int c = this.count;
            semaphore.release();
            return c;
        }

        void add() throws InterruptedException {
            semaphore.acquire();
            this.count++;
            System.out.println(" > 输出： " + this.count);
            semaphore.release();
        }

        void dec() throws InterruptedException {
            semaphore.acquire();
            this.count--;
            semaphore.release();
        }
    }

    private static class Handler implements Runnable {

        private String name;

        private int seq;

        private int total;

        private Counter counter;

        public Handler(String name, int seq, Counter counter, int total) {
            this.name = name;
            this.seq = seq;
            this.counter = counter;
            this.total = total;
        }

        @Override
        public void run() {
            try {
                while (this.seq != this.counter.getCount() + 1) {
                    Thread.sleep(1000);
                }
                this.counter.add();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}